#ifndef _TYPES_H_
#define _TYPES_H_

#define MAX_NAME_LEN    128     
#define NEWFS_ASSIGN_FNAME(pnewfs_dentry, _fname)\ 
                                        memcpy(pnewfs_dentry->fname, _fname, strlen(_fname))



/******************************************************************************
* SECTION: Type def
*******************************************************************************/
struct custom_options {
	const char*        device;
};
typedef int          boolean;
typedef uint16_t     flag16;
typedef enum newfs_file_type {
    NEWFS_REG_FILE,
    NEWFS_DIR
} NEWFS_FILE_TYPE;


/******************************************************************************
* SECTION: Macro
*******************************************************************************/
#define TRUE                    1
#define FALSE                   0
#define UINT32_BITS             32
#define UINT8_BITS              8

#define MYFS_MAGIC_NUM           0x52415453  
#define MYFS_SUPER_OFS           0              //超级块的偏移（字节）
#define MYFS_ROOT_INO            0              //超级块在位图中的索引



#define MYFS_ERROR_NONE          0
#define MYFS_ERROR_ACCESS        EACCES
#define MYFS_ERROR_SEEK          ESPIPE     
#define MYFS_ERROR_ISDIR         EISDIR
#define MYFS_ERROR_NOSPACE       ENOSPC
#define MYFS_ERROR_EXISTS        EEXIST
#define MYFS_ERROR_NOTFOUND      ENOENT
#define MYFS_ERROR_UNSUPPORTED   ENXIO
#define MYFS_ERROR_IO            EIO     /* Error Input/Output */
#define MYFS_ERROR_INVAL         EINVAL  /* Invalid Args */

#define MYFS_MAX_FILE_NAME       128    //最大文件名长度
#define MYFS_INODE_PER_FILE      1      //每个文件最多一个inode
#define MYFS_DEFAULT_PERM        0777   //文件属性中的mode的默认值
#define MYFS_EXT2_BlkSize        1024   //EXT2中一个块的大小
#define MYFS_BLK_PER_FILE        6      //每个文件最多6个EXT2下的块
#define MYFS_INO_PER_BLK         8     //每个磁盘块存储的文件inode数
// //这两个目前没找到用处
// #define MYFS_IOC_MAGIC           'S'
// #define MYFS_IOC_SEEK            _IO(MYFS_IOC_MAGIC, 0)
// //暂时没找到使用的地方，不过我猜和写回有关
// #define MYFS_FLAG_BUF_DIRTY      0x1        
// #define MYFS_FLAG_BUF_OCCUPY     0x2
/******************************************************************************
* SECTION: Macro Function
*******************************************************************************/
#define MYFS_IO_SZ()                     (super_m.sz_io)        //设备的IO大小
#define MYFS_DISK_SZ()                   (super_m.sz_disk)      //设备的磁盘大小
#define MYFS_DRIVER()                    (super_m.driver_fd)    //设备的文件句柄
#define MYFS_INODE_SIZE()                (sizeof(struct newfs_inode))
//向下对齐，比如round为512，value为500。则对到0
#define MYFS_ROUND_DOWN(value, round)    (value % round == 0 ? value : (value / round) * round)     
//向上对齐，比如round为512，value为500，则对到512. 
#define MYFS_ROUND_UP(value, round)      (value % round == 0 ? value : (value / round + 1) * round)  

#define MYFS_BLKS_SZ(blks)               (blks * MYFS_IO_SZ())              //16个IO size，相当于8个文件块大小(8kb)
 //为输入dentry分配分配文件名
#define MYFS_ASSIGN_FNAME(psfs_dentry, _fname)\ 
                                        memcpy(psfs_dentry->fname, _fname, strlen(_fname))         
//计算ino在磁盘上的偏移
#define MYFS_INO_OFS(ino)                (super_m.inode_offset + MYFS_BLKS_SZ(ino / MYFS_INO_PER_BLK) + \
                                                                       (ino % MYFS_INO_PER_BLK) * MYFS_INODE_SIZE())    
//计算文件号为ino的文件在磁盘上的偏移           
#define MYFS_DATA_OFS(ino)               (super_m.data_offset + ino * MYFS_BLKS_SZ(MYFS_BLK_PER_FILE * 2))   
#define MYFS_IS_DIR(pinode)              (pinode->dentry->ftype == NEWFS_DIR)   //返回输入inode指向的是否为文件夹
#define MYFS_IS_REG(pinode)              (pinode->dentry->ftype == NEWFS_REG_FILE) //返回输入inode指向的是否为文件













/******************************************************************************
* SECTION: NEWFS Specific Structure - In memory structure
*******************************************************************************/
struct newfs_dentry_m;
struct newfs_inode_m;
struct newfs_super_m;

struct newfs_inode_m
{
    int                ino;                           /* 在inode位图中的下标 */
    int                size;                          /* 文件已占用空间 */
    int                dir_cnt;                     
    struct newfs_dentry_m* dentry;                        /* 指向该inode的dentry */
    struct newfs_dentry_m* dentrys;                       /* 所有目录项 */
    uint8_t*           data;                           //inode指向的数据的指针
};  

struct newfs_dentry_m
{
    char               fname[MAX_NAME_LEN];
    struct newfs_dentry_m* parent;                        /* 父亲Inode的dentry */
    struct newfs_dentry_m* brother;                       /* 兄弟 */
    int                ino;                                //它指向的inode在inode位图中的下标
    struct newfs_inode_m*  inode;                         /* 指向inode */
    NEWFS_FILE_TYPE      ftype;
};

struct newfs_super_m
{
    int                driver_fd;
    
    int                sz_io;
    int                sz_disk;
    int                sz_usage;
    
    int                max_ino;
    uint8_t*           map_inode;                   //主存中map_inode的指针
    int                map_inode_blks;              // inode位图占用的块数
    int                map_inode_offset;            // inode位图在磁盘上的偏移
   
    uint8_t*           map_data;                    //主存中mao_data的指针
    int                map_data_blks;               // data位图占用的块数
    int                map_data_offset;             // data位图在磁盘上的偏移

    int                inode_offset;                //磁盘上inode的偏移
    int                data_offset;                 //磁盘上数据的偏移

    boolean            is_mounted;

    struct newfs_dentry_m* root_dentry;
};
//内联函数new_dentry
/*
    用于创建新的目录项

*/
static inline struct newfs_dentry_m* new_dentry(char * fname, NEWFS_FILE_TYPE ftype) {
    struct newfs_dentry_m * dentry = (struct newfs_dentry_m *)malloc(sizeof(struct newfs_dentry_m));
    memset(dentry, 0, sizeof(struct newfs_dentry_m));
    NEWFS_ASSIGN_FNAME(dentry, fname);
    dentry->ftype   = ftype;
    dentry->ino     = -1;
    dentry->inode   = NULL;
    dentry->parent  = NULL;
    dentry->brother = NULL;    
    return dentry;                                        
}

/******************************************************************************
* SECTION: NEWFS Specific Structure - Disk structure
*******************************************************************************/
struct newfs_super {
    uint32_t magic;
    int      fd;
    /* TODO: Define yourself */
    int      sz_usage;                    // 磁盘已经使用的字节
    int      max_ino;                     // 最多支持的文件数

    int      map_inode_blks;              // inode位图占用的块数
    int      map_inode_offset;            // inode位图在磁盘上的偏移

    int      map_data_blks;               // data位图占用的块数
    int      map_data_offset;             // data位图在磁盘上的偏移

    int      inode_offset;                //索引节点在磁盘上的偏移
    int      data_offset;                 //数据在磁盘上的偏移
};

struct newfs_inode {
    uint32_t ino;                         // 在inode位图中的下标 
    /* TODO: Define yourself */
    int                size;              // 文件已占用空间 
    int                dir_cnt;           // 如果是目录类型文件，下面有几个目录项
    NEWFS_FILE_TYPE     ftype;   
};

struct newfs_dentry {
    char     name[MAX_NAME_LEN];
    uint32_t ino;                         //指向的inode号
    /* TODO: Define yourself */
    NEWFS_FILE_TYPE     ftype;
};

#endif /* _TYPES_H_ */